/***********************************************
*		The Admin Script
*		version 0.65 (2.6.2008)
*
* Author: Matthew Smith
*
* Description: This little script has been developed
*	to provide an easier way to accomplish various
*	administrative tasks such as collecting information
*	about various computers, updating software,
*	and creating reports. There have been several
*	prior versions of this script, such as swupdate.vbs
*	but with the development of this script, those will be
*	discontinued.
*
*	This script contains a library of useful tools that
*	use the WMI interface to pull various information
*	or execute tasks on both the local machine or on any
*	networked computer on which you have the apropriate
*	access rights. This general routines can be combined
*	in various ways to perform tasks, create reports, and
*	accomplish any other administrative task you can think of.
*	Of course if you need more information you can feel
*	free to write more functions ;)
*
*	
*/

// includes
eval(includeExtJS("lib\\wmiNetworkTools.js"));
eval(includeExtJS("lib\\wmiRegistryTools.js"));
eval(includeExtJS("lib\\wmiSystemTools.js"));
eval(includeExtJS("lib\\digiLogger.js"));

/** GLOBAL VARIABLES
* things that could be useful to set...
*
* Login Credentials
* a security risk if other people can access
* the script!!!
***	Administrator Username: */
var adminUserName = "CA\\msmith1"
/**	Administrator Password: */
var adminPass = ""
/** END GLOBAL VARIABLES **/

// let's configure the global log
var caLog = new digiLogger("ca.log");
caLog.logHeader = "===========================================\n====== CA Network Maintenance Script ======\n===========================================\n"
caLog.headerEnabled = true;


main(); // lets go!

/** TRAFFIC CONTROL
* you know, so you can do certain tasks, instead of all at once!
* and yes, i know it's rediculous to have a main function in a script
* but it makes the C coder in me happy
*/
function main() {
	var args = WScript.Arguments; // get any arguments passed on the command line
	var count = 0; // create a counter
	var setupFlag = 0; // this will be set to 1 if a setup is asked for
	
	// now lets step through the arguments!
	// eventually we should be able to perform all sorts of cool actions using the command line!
	while( count < args.length ) {
		//WScript.Echo("Argument " + count + ": " + args.item(count)); // debug statment that prints each argument out
		// lets check out our arguments and do some stuff!
		switch( args.item(count) ) {
			default:
				WScript.Echo("Please specify an operation on the command line.\n\nPass 'help' as an argument to get help.");
				break;
			case "help":
				WScript.Echo("this is the help info");
				break;
			case "debug":
				okgoDebug();
				break;
			case "teacher":
				// check for previously selected setups
				if( setupFlag == true ) {
					WScript.Echo("Error: You can only select one setup type at a time");
					return;
				} else { setupFlag = true; } // prevent other setups from running
				
				count++; // let's increment the counter and grab the next argument (should be the target)
				var targetSystem = args.item(count); // get the next argument as the target
				
				WScript.Echo("Performing teacher setup routine");
				// call the teacher setup routine
				caSetupTeacher(targetSystem);
				WScript.Echo("Done.");
				break;
			case "student":
				// check for previously selected setups
				if( setupFlag == true ) {
					WScript.Echo("Error: You can only select one setup type at a time");
					return;
				} else { setupFlag = true; } // prevent other setups from running
				
				WScript.Echo("this should call the student setup routine");
				// call the student setup routine
				break;
			case "install":
				WScript.Echo("this should perform software updates/installs");
				break;
		}
		count++;
	}
	
	if( args.length == 0 ) {
		//default operation (no arguments)
		WScript.Echo("This program takes command line arguments");
	}
}

/* Teacher Controller
 * 
 */

function caSetupTeacher(target) {
	// we're just going to call a bunch of functions for now. no logic
	caLog.log("Operating on: " + target)
	caDomainSetup(target);
	caDHCPSetup(target);
	caProxySettings(target);
	caTeacherGroupSetup(target);
	caRemoteDesktopEnable(target);
	caSoftwareUpdate(target);
	caWindowsUpdate(target);
}

/** SITE SPECIFIC TOOLS
* These tools are intended to perform actions specific to
* administering computers at Covenant Academy. For
* general, reusable routines (which are called here), see
* below.
*/

/** TEACHER SYSTEM CONFIGURATION METHODS
*/

/** STEP 1: Setup On Domain
* We shall check to see if the computer is in the CA domain.
* If not, we must do that.
*/
function caDomainSetup(computer) {
	// the WMI function to set the domain was added in XP,
	// so no dice for W2K, we must do it by hand....
	
	// gather info...
	netSettings = networkToolsGetSettings(computer); // get network settings
	compInfo = systemToolsGetSettings(computer); // get computer info
	
	// first we shall check the domain to see if we need to do anything
	if( netSettings.DNSDomain[0] == "CA" ) {
		// log that we are on the right domain
		caLog.log("Domain Setup:\tComputer is configured on correct domain (" + netSettings.DNSDomain[0] + ")");
		caLog.log("Domain Setup:\tThe DNS name is " + netSettings.DNSHostName[0] + "." + netSettings.DNSDomain[0] + ".local");
		return -1; // and we don't need to do anything
	}
	
	// if we're here, than the domain isn't correct
	
	// lets check the OS
	// first we need to make the regexp object to compare with
	var reWin2K = new RegExp("Windows 2000","i"); // case insensitive
		
	if( compInfo.OS.match(reWin2K) ){
		// alert or log that we need to do the domain setup by HAND
		// perhaps pause and wait
		caLog.log("Domain Setup:\tComputer is not configured on the correct domain (currently " + netSettings.DNSDomain[0] + ") but");
		caLog.log("Domain Setup:\tis running an operating system that does not support scripted domain joins. Please join domain manually");
		caLog.log("Domain Setup:\tbefore proceeding.");
		return 0; // return error code
	} else {
		// code to attempt adding system to the correct domain
		networkToolsJoinDomain(computer,"CA");
	}
	// perhaps we could perform some error checking to ensure that the domain has been joined
	netSettings = networkToolsGetSettings(computer); // recheck
	
	if( netSettings.DNSDomain[0] != "CA" ){
		// Error
		caLog.log("Domain Setup:\tCould not configure computer on domain. Please join manually.");
		return 0;
	} else {
		return -1;
	}
}


/** STEP 2: Set Up DHCP
* After adding to the domain, all computers must (except for
* special circumstances) use DHCP to retrieve an IP.
* 
* We must check the DHCP status first, because if the machine
* has a static IP we should record that for the records. The
* MAC address should be recorded along with the static IP
* so that a DHCP reservation can be created. This data should be
* logged!
*/
function caDHCPSetup(computer) {
	// get the settings
	var netSettings = networkToolsGetSettings(computer);
	
	// lets see if it's enabled first:
	if( netSettings.DHCP[0] ) {
		// log
		caLog.log("DHCP Setup:\tDHCP Enabled");
		caLog.log("DHCP Setup:\tCurrently using IP " + netSettings.IP[0]);
		caLog.log("DHCP Setup:\tMAC Address is " + netSettings.MAC[0]);
		return -1;
	} else {
		// log
		caLog.log("DHCP Setup:\tDHCP Disabled");
		caLog.log("DHCP Setup:\tCurrent IP is " + netSettings.IP[0]);
		caLog.log("DHCP Setup:\tMAC Address is " + netSettings.MAC[0]);
		
		caLog.log("DHCP Setup:\t Enabling DHCP...")
		networkToolsEnableDHCP(computer); // enable DHCP
		// recheck to see if the settings stuck!
		netSettings = networkToolsGetSettings(computer);
		if( !netSettings.DHCP[0] ) {
			caLog.log("DHCP Setup:\tUnable to enable DHCP, please do this manually before proceeding.");
			return 0;
		} else {
			caLog.log("DHCP Setup:\tDHCP successfully enabled, now using IP " + netSettings.IP[0]);
			return -1;
		}
	}
}

/** STEP 2a: Set Up Proxy
* After a teacher computer has been set up on the DHCP reservation
* list, we need to add the correct proxy settings so that they can
* access the less restrictive filter.
* We could also have a function to set up general filtering.
* Proxy server: 192.168.0.99
* General Port: 8081
* Less Restricted Port: 80 (for IPs > 192.168.0.175)
*/
function caProxySettings(computer) {
	// let's check the proxy settings first
	// *TODO* need to add logic to add local domains to bypass list
	var proxyEnabled = networkToolsGetProxySettings(computer, "Proxy_Enabled");
	var proxyServer = networkToolsGetProxySettings(computer, "Proxy_Server");
	var proxyServerAddress = "192.168.0.99:80" // for easy changing
	//var reProxyServer = new RegExp(proxyServerAddress, "i");
	
	if( proxyEnabled == true) {
		if( proxyServer == proxyServerAddress ) {
			caLog.log("Proxy Setup:\tProxy server enabled and properly configured.");
			caLog.log("Proxy Setup:\tServer: " + proxyServer)
			return -1; // exit with success
		} else {
			caLog.log("Proxy Setup:\tProxy enabled but not configured. Configuring...");
			networkToolsSetProxySettings(computer, "Proxy_Server", proxyServerAddress); // set the proxy server 
			caLog.log("Proxy Setup:\tProxy now set to " + proxyServerAddress)
			return -1; // exit with success
		}
	} else {
		// lets set everything.
		networkToolsSetProxySettings(computer, "Proxy_Server", proxyServerAddress); // set the proxy server
		networkToolsSetProxySettings(computer, "Proxy_Enabled", true); // enable proxy
		caLog.log("Proxy Setup:\tProxy enabled and set to " + proxyServerAddress)
		return -1;
	}
}

/** STEP 3: Add Tachers (domain group) to the Local Administrator Group
* self descriptive title, don't you think?
*/
function caTeacherGroupSetup(computer) {
	// all I've found so far is a command that needs to be run
	// so we'll use WMI to remotely execute a command ;)

	systemToolsExecuteCmd(computer, "net.exe localgroup \"Administrators\" \"CA\\Teachers\" /ADD")
	caLog.log("Group Setup:\tTeachers added to Local Administrator group")
}

/** STEP 4: Enable Remote Desktop on XP systems
* I don't even know if this script will work on XP yet...
*/
function caRemoteDesktopEnable(computer) {
	// this is only done on XP machines
	// and we'll do it with a registry call, not the WMI method
	var compInfo = systemToolsGetSettings(computer)
	var reWinXP = new RegExp("Windows XP","i");
	
	if( compInfo.OS.match(reWinXP) ){
		// let's check the status
		var status = registryToolsReadValue(computer, "HKLM", "SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\", "fDenyTSConnections", "REG_DWORD");
		if( status == 0 ) {
			// it's already enabled
			caLog.log("Remote Desktop Setup:\tRemote Desktop is already enabled");
		} else if( status == 1 ) {
			// it's not enabled
			caLog.log("Remote Desktop Setup:\tEnabling Remote Desktop...");
			registryToolsWriteValue(computer, "HKLM", "SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\", "fDenyTSConnections", "REG_DWORD", 0);
			status = registryToolsReadValue(computer, "HKLM", "SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\", "fDenyTSConnections", "REG_DWORD");
			if( status == 0 ) {
				caLog.log("Remote Desktop Setup:\tRemote Desktop successfully enabled!");
			}
		}
	} else {
		caLog.log("Remote Desktop Setup:\tRemote Desktop not supported on this machine");
	}
}

/** STEP 5: Update and Install Software
* Install/Update: Shockwave, Flash, Quicktime, Windows Media
* Player, Adobe Reader, JAVA, and a Timezone update patch.
*/
function caSoftwareUpdate(computer) {
	/* this is going to be rather entertaining
	 * the best way to handle this is probably
	 * by creating a seperate .js module for 
	 * each program we wish to install.
	 * 
	 * then we can use a file system function to load
	 * each module and execute it.
	 * 
	 * so we can call these *.app.js
	 * 
	 * this will make it easy to add new programs,
	 * each with their own install logic.
	 * 
	 * each module could return specific information...
	 * 
	 * from each module, we want to know some stuff. 
	 * each module should make an object with the
	 * name of the application, install status,
	 * version numbers... mmmm
	 */
	 
	 
	
}

/** STEP 6: Perform a Windows Update
* got it?
*/
function caWindowsUpdate(computer) {
	// perhaps this could be done with some general
	// wmi calls? if so, LIBRARY FUNCTION!!!
	// for now lets just call an external script...
}

/** END SITE SPECIFIC TOOLS **/

/** DEBUG AREA **/

function okgoDebug() {
/*
	var network = networkToolsGetSettings(".");
	
	for( i=0; i<network.IP.length; i++ ){
		WScript.Echo(network.IP[i]);
	}
	for( i=0; i<network.MAC.length; i++ ){
		WScript.Echo(network.MAC[i]);
	}
	for( i=0; i<network.DHCP.length; i++ ){
		WScript.Echo(network.DHCP[i]);
	}
	for( i=0; i<network.DNSDomain.length; i++ ){
		WScript.Echo(network.DNSDomain[i]);
	}	
	for( i=0; i<network.DNSHostName.length; i++ ){
		WScript.Echo(network.DNSHostName[i]);
	}
	
//	caDomainSetup("."); // test
//	caDHCPSetup(".");

	var system = systemToolsGetSettings(".");
	WScript.Echo(system.UserName);
	WScript.Echo(system.OS);
	WScript.Echo(system.OSServicePack);
	WScript.Echo(system.OSVersion);
	
	var osMatch = new RegExp("Windows 2000", "i")
	
	if(system.OS.match(osMatch)){ WScript.Echo("It's Windows 2000!!!"); }
	
	var myLog = new digiLogger("test.log");
	myLog.headerEnabled = true;
	myLog.timeStamp = false;
	myLog.logHeader = "this is my header, line 1\nand this is line 2!\nand this is line 3";
	
	myLog.log("Hello!\r\n")
	myLog.log("test again");
	myLog.writeHeader();
	myLog.headerEnabled = false;
	myLog.log("now the log header is disabled");
	myLog.writeHeader();
	myLog.log("we try to write the header but it shouldn't be output");
	myLog.enabled = false;
	myLog.log("this should not be logged\n new line test\nnewline!")
	myLog.enabled = true;
	myLog.log("this will be logged");
	myLog.log("this is a test of the \n new line fix\nand another line")
	caLog.log("hello world!")
*/
	
	// test suite for digiModularInstaller
	eval(includeExtJS("lib\\digiModularInstaller.js"));
	
	var testInstall = new digiModularInstaller("installers");
	WScript.Echo(" Properties " + testInstall.moduleDirectory );
	testInstall.install();
} 

/** END DEBUG AREA **/

/** OBJECT CONSTRUCTORS
* because it makes life easier
*/

// none for now

/** END CONSTRUCTORS **/

/** Include Function
* Allows for the inclusion of external JS libraries
* call using eval( includeExtJS(fileName) );
* the include statment must occur before the first call to an external routine
*/

function includeExtJS(fileName) {
	var fso = new ActiveXObject('Scripting.FileSystemObject'); // create the file system object
	if( !fso.FileExists(fileName) ) { return -1; } // check for file existance and fail if no file
	var file = fso.OpenTextFile(fileName); // open file
	var stream = file.ReadAll(); // read file
	file.Close(); // close file
	return stream; // send it back (you need to evaluate the return)
}